package com.hailiang.study.javase.java.util;

import org.junit.Test;

import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * Map.computeIfAbsent()
 * 在JAVA8的Map接口中，增加了一个方法computeIfAbsent，此方法签名如下：
 *    public V computeIfAbsent(K key, Function<? super K,? extends V> mappingFunction)
 *
 * 此方法首先判断缓存MAP中是否存在指定key的值，如果不存在，会自动调用mappingFunction(key)计算key的value，然后将key = value放入到Map。
 * 如果mappingFunction(key)返回的值为null或抛出异常，则不会有记录存入map
 */
public class Map_computeIfAbsent {

    @Test
    public void testComputeIfAbsent01() {
        Map<String, String> map = new HashMap<>();

        // 原来的实现方式
        if (!map.containsKey("huawei")) {
            map.put("huawei", "huawei" + "=华为");
        }

        // 使用computeIfAbsent，同上面方法效果一样，但更简洁
        map.computeIfAbsent("huawei", key -> key + "=华为");

        System.out.println(map);
    }


    @Test
    public void testComputeIfAbsent02() {
        Map<String, AtomicInteger> map = new LinkedHashMap<>();
        List<String> letterList = Arrays.asList(new String[]{"h", "e", "l", "l", "o", "w", "o", "r", "l", "d"});

        letterList.forEach(letter -> {
            // 如果key不存在，则使用新的value替换缓存中
            map.computeIfAbsent(letter, key -> new AtomicInteger()).getAndIncrement();
        });

        map.forEach((k, v) -> System.out.println(k + "=" + v));
    }


    @Test
    public void testComputeIfAbsent03() {
        Map<String, List<String>> map = new HashMap<>();
        map.computeIfAbsent("ProgrammingLanguage", k -> new ArrayList<>()).add("Java");
        map.computeIfAbsent("ProgrammingLanguage", k -> new ArrayList<>()).add("Python");
        map.computeIfAbsent("ProgrammingLanguage", k -> new ArrayList<>()).add("C#");
        map.computeIfAbsent("Database", k -> new ArrayList<>()).add("Mysql");
        map.computeIfAbsent("Database", k -> new ArrayList<>()).add("Oracle");

        map.forEach((k, v) -> System.out.println(k + " " + v));
    }
}
